package com.kalvan.admin.system.controller;


import com.github.pagehelper.Page;
import com.kalvan.admin.system.service.DictService;
import com.kalvan.commons.constant.LogGroup;
import com.kalvan.commons.db.system.mapper.DictMapper;
import com.kalvan.commons.db.system.model.Dict;
import com.kalvan.commons.dto.system.DictImport;
import com.kalvan.core.exception.BizException;
import com.kalvan.core.mybatis.PageInfo;
import com.kalvan.core.utils.BeanUtils;
import com.kalvan.core.utils.Sysdate;
import com.kalvan.core.utils.ValidationUtil;
import com.kalvan.core.valid.Add;
import com.kalvan.core.valid.Edit;
import com.kalvan.remoteserver.iface.IDictCacheUpdate;
import com.kalvan.web.controller.BaseController;
import com.kalvan.web.dict.DictCache;
import com.kalvan.web.excel.ExcelUtil;
import com.kalvan.web.exception.AdminReturnCode;
import com.kalvan.web.log.LogType;
import com.kalvan.web.log.annotation.SysLog;
import com.kalvan.web.servlet.annotation.Permission;
import com.kalvan.web.servlet.response.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

/**
 * 数据字典配置Controller
 *
 * @author kalvan
 * @date 2020-08-23 15:07:36
 */
@SysLog(group = LogGroup.DICT)
@Api(tags = {"数据字典配置"})
@RestController
@RequestMapping("system/dict")
@Slf4j
public class DictController extends BaseController {
    @Resource
    DictService dictService;
    @Resource
    DictMapper dictMapper;
    /**
     * 广播接口
     */
    @Reference(interfaceClass = IDictCacheUpdate.class, check = false, cluster = "broadcast")
    IDictCacheUpdate iDictCacheUpdate;
    @Resource
    DictCache dictCache;

    /**
     * 分页查询
     *
     * @param params 查询参数
     * @return R
     */
    @ApiOperation("分页查询")
    @PostMapping("list")
    @Permission("admin:system:dict:list")
    public R list(PageInfo pageInfo, @RequestParam Map<String, String> params) {
        Page data = dictService.queryPage(pageInfo, params);
        return R.ok().putPage(data);
    }

    /**
     * 根据主键查询详情
     *
     * @param id 主键
     * @return R
     */
    @ApiOperation("主键查询")
    @GetMapping("info/{id}")
    @Permission("admin:system:dict:info")
    public R info(@PathVariable("id") Long id) {
        Dict dict = dictService.findById(id);
        if (dict == null) {
            throw new BizException(AdminReturnCode.REQUEST_ILLEGAL);
        }
        return R.ok().putData(dict);
    }

    private static final int DOWNLOAD_MAX_COUNT = 20000;

    /**
     * 下载
     *
     * @param params   查询参数
     * @param response response
     * @throws Exception 抛出异常拦截器统一处理
     */
    @ApiOperation("下载数据字典配置")
    @PostMapping("download")
    @Permission("admin:system:dict:download")
    public void download(@RequestParam Map<String, String> params, HttpServletResponse response) throws Exception {
        PageInfo pageInfo = new PageInfo();
        pageInfo.setPage(1);
        pageInfo.setLimit(DOWNLOAD_MAX_COUNT);
        Page data = dictService.queryPage(pageInfo, params);
        String filename = "数据字典配置";
        if (data.getTotal() > DOWNLOAD_MAX_COUNT) {
            throw new BizException(AdminReturnCode.PARAM_REGION_OVER.formatDesc("下载条数", DOWNLOAD_MAX_COUNT));
        }
        filename = filename + Sysdate.getTimeStr(true);
        ExcelUtil.download(filename, response, Dict.class, data);
    }

    /**
     * 新增数据字典配置
     *
     * @param dictImport dictImport
     * @return R
     */
    @SysLog(remark = "新增数据字典配置", type = LogType.ADD)
    @ApiOperation("新增数据字典配置")
    @PostMapping("add")
    @Permission("admin:system:dict:add")
    public R add(@Validated({Add.class}) DictImport dictImport) {
        dictService.add(BeanUtils.newAndCopy(dictImport, Dict.class));
        return R.ok();
    }

    /**
     * 数据字典配置导入模板下载
     *
     * @param response response
     * @throws Exception 抛出异常拦截器统一处理
     */
    @ApiOperation("数据字典配置导入模板下载")
    @GetMapping("downloadTemplate")
    @Permission("admin:system:dict:upload")
    public void downloadTemplate(HttpServletResponse response) throws Exception {
        ExcelUtil.downloadTemplate(templateRootPath + "com/kalvan/admin/数据字典配置-模板.xls", response);
    }

    /**
     * 导入数据字典配置
     *
     * @param file file
     * @return R
     */
    @SysLog(remark = "导入数据字典配置", type = LogType.IMPORT)
    @ApiOperation("导入数据字典配置")
    @PostMapping("upload")
    @Permission("admin:system:dict:upload")
    public R upload(@RequestParam MultipartFile file) throws Exception {
        List<DictImport> importList = ExcelUtil.importExcel(file, 1, 1, DictImport.class);
        for (DictImport dictImport : importList) {
            String error = ValidationUtil.validation(dictImport, new Class[]{Add.class});
            if (StringUtils.isNotBlank(error)) {
                throw new BizException(AdminReturnCode.PARAM_ILLEGAL.formatDesc(error));
            }
            dictService.add(BeanUtils.newAndCopy(dictImport, Dict.class));
        }
        return R.ok(AdminReturnCode.SUCCESS_IMPORT.getFormatDesc(importList.size()));
    }

    /**
     * 修改数据字典配置
     *
     * @param dictImport dictImport
     * @return R
     */
    @SysLog(remark = "修改数据字典配置", type = LogType.EDIT)
    @ApiOperation("修改数据字典配置")
    @PostMapping("edit")
    @Permission("admin:system:dict:edit")
    public R edit(@Validated({Edit.class}) DictImport dictImport) {
        if (dictImport.getId() == null) {
            return R.error(AdminReturnCode.REQUEST_ILLEGAL.getMsg());
        }
        dictService.edit(BeanUtils.newAndCopy(dictImport, Dict.class));
        return R.ok();
    }

    /**
     * 根据主键删除数据字典配置
     *
     * @param ids ids
     * @return R
     */
    @SysLog(remark = "删除数据字典配置", type = LogType.DELETE)
    @ApiOperation("删除数据字典配置")
    @PostMapping("delete")
    @Permission("admin:system:dict:delete")
    public R delete(Integer[] ids) {
        if (ArrayUtils.isEmpty(ids)) {
            return R.error(AdminReturnCode.REQUEST_ILLEGAL.getMsg());
        }
        int num = dictService.deleteBatch(ids);
        return R.ok(AdminReturnCode.SUCCESS_DELETE.getFormatDesc(num));
    }

    @ApiOperation("更新缓存")
    @Permission("admin:system:dict:updateCache")
    @PostMapping("updateCache")
    public R updateCache(String dictType) {
        dictCache.updateDictCache(dictType);
        //广播通知更新
        log.info("开始广播通知更新缓存");
        boolean flag = iDictCacheUpdate.clearDictCache(dictType);
        if (flag) {
            return R.ok();
        } else {
            return R.error("更新失败");
        }
    }

    @ApiOperation("获取所有字典类型")
    @PostMapping("allType")
    public R allType() {
        return R.ok().putData(dictMapper.selectAllType());
    }

}
